import numpy
import scipy
#from scipy import interpolate

from Bases import BaseObject, setID
from DeviceSystem.Groups.Group import GroupBase

class BaseController(BaseObject):
    _saved_attributes = ['id', 'name']
    def __init__(self, **kwargs):
        super(BaseController, self).__init__(**kwargs)
        self.register_signal('value_update', 'settings_changed')
        if 'deserialize' not in kwargs:
            self.id = setID(kwargs.get('id'))
            self.name = kwargs.get('name')
        self.src_object = kwargs.get('src_object')
        self.src_attr = kwargs.get('src_attr')
        self.src_index = kwargs.get('src_index')
        self.obj_scale_factor = float(kwargs.get('obj_scale_factor', 255))
        if self.src_object is not None:
            print self.name, self.src_object
    
    def on_interval(self, timeV):
        value = self.calclulate_value(timeV)
        #self.emit('value_update', value=value, timeV=timeV, id=self.id)
        if value is not False and self.src_object is not None:
            if self.src_index:
                l = getattr(self.src_object, self.src_attr)
                l[self.src_index] = value * self.obj_scale_factor
                setattr(self.src_object, self.src_attr, l)
            else:
                setattr(self.src_object, self.src_attr, value * self.obj_scale_factor)
            #print self.name, self.src_object, value
    
    def calclulate_value(self, timeV):
        pass
    
        
class KeyframeController(BaseController):
    _saved_class_name = 'KeyframeController'
    _saved_attributes = ['hook_style', 'keyframes']
    def __init__(self, **kwargs):
        super(KeyframeController, self).__init__(**kwargs)
        if 'deserialize' not in kwargs:
            self.hook_style = kwargs.get('hook_style', 'linear')
            self.keyframe_array = None
            self.keyframes = {}
            keyframes = kwargs.get('keyframes', {})
            self.add_keyframes(keyframes)
        self.update_keyframe_array()
        
    def on_settings_changed(self, **kwargs):
        d = kwargs.get('keyframes')
        if d:
            self.add_keyframes(d)
    def store_value(self, timeV, value=None):
        if value:
            self.add_keyframes({timeV:value / self.obj_scale_factor})
        else:
            self.store_current_value(timeV)
    def store_current_value(self, timeV):
        if self.src_index:
            value = [x / self.obj_scale_factor for x in getattr(self.src_object, self.src_attr)[self.src_index]]
        else:
            value = getattr(self.src_object, self.src_attr) / self.obj_scale_factor
        self.add_keyframes({timeV:value})
        print 'controller store current: value=%s, keyframes=%s' % (value, self.keyframes)
    def add_keyframes(self, d):
        self.keyframes.update(d)
        self.update_keyframe_array()
        #self.spline = interpolate.BivariateSpline(self.keyframe_array[0], self.keyframe_array[1])
        self.emit('settings_changed', keyframes=self.keyframes)
    def update_keyframe_array(self):
        keys = self.keyframes.keys()
        keys.sort()
        l1 = [float(key) for key in keys]
        l2 = [float(self.keyframes.get(key)) for key in keys]
        self.keyframe_array = numpy.array([l1, l2])
        flag = True
        if len(l2) == 0 or l2.count(l2[0]) == len(l2):
            flag = False
        self.does_change = flag
        
    def calclulate_value(self, timeV):
        #return self.spline.ev(timeV)
        value = numpy.interp(timeV, self.keyframe_array[0], self.keyframe_array[1])
        #print 'timeV=%s, value=%s, kframes=%s' % (timeV, value, self.keyframes)
        return value
        
class FunctionalController(BaseController):
    _saved_class_name = 'FunctionalController'
    _saved_attributes = ['expression']
    def __init__(self, **kwargs):
        super(FunctionalController, self).__init__(**kwargs)
        if 'deserialize' not in kwargs:
            exp = kwargs.get('expression', 'y=x')
            if '=' in exp:
                exp = exp.split('=')[1]
            self.expression = exp
        self.function = kwargs.get('function', self._default_function)
    def on_settings_changed(self, **kwargs):
        exp = kwargs.get('expression')
        if exp:
            self.expression = exp
    @property
    def expression(self):
        return self._expression
    @expression.setter
    def expression(self, value):
        self._expression = value
        self.emit('settings_changed', expression=value)
    def _default_function(self, timeV):
        x = timeV
        return eval(self.expression())
    def calclulate_value(self, timeV):
        return self.function(timeV)
